#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_NONSTDC_NO_DEPRECATE
#include"StringPool.h"
#include"variable.h"
#include"DependencyInstance.h"
#include"DependencyReader.h"
#include"MSTReader.h"
#include"RelationalFeature.h"
#include"Util.h"
using namespace std;

MSTReader::MSTReader() : DependencyReader(){}

MSTReader::MSTReader(bool labeled, bool hasEnd) : DependencyReader(){
	this->labeled = labeled;
	this->hasEnd = hasEnd;
}

bool MSTReader::fileContainsLabels(const char *filename){
	FILE* in;
	in = fopen(filename, "r");
	char line[10000];
	fgets(line, 10000, in);
	fgets(line, 10000, in);
	fgets(line, 10000, in);
	fgets(line, 10000, in);
	fclose(in);
	int str_len = (int)(strlen(line));
	line[str_len] = '\0';
	string tmp = string(line);
	string* s = pool->get(tmp);

	string* str = Util::trim(s);

	if(str->length() > 0){
		pool->push_back(s);
		pool->push_back(str);
		return true;
	}
	else{
		pool->push_back(s);
		pool->push_back(str);
		return false;
	}
}

DependencyInstance* MSTReader::getNext(){
	char line[1000000];
	fgets(line, 1000000, inputReader);
	int str_len = (int)(strlen(line));
	line[str_len] = '\0';
	if(feof(inputReader)){
		fclose(inputReader);
		return NULL;
	}
	string tmp = string(line);
	string* forms_line = pool->get(tmp);

	fgets(line, 1000000, inputReader);
	str_len = (int)(strlen(line));
	line[str_len] = '\0';
	tmp = string(line);
	string* pos_line = pool->get(tmp);

	string* deprel_line;
	if(labeled){
		fgets(line, 1000000, inputReader);
		str_len = (int)(strlen(line));
		line[str_len] = '\0';
		tmp = string(line);
		deprel_line = pool->get(tmp);
	}
	else{
		deprel_line = pool->get(*pos_line);
	}

	fgets(line, 1000000, inputReader);
	str_len = (int)(strlen(line));
	line[str_len] = '\0';
	tmp = string(line);
	string* heads_line = pool->get(tmp);

	fgets(line, 1000000, inputReader);
	str_len = (int)(strlen(line));
	line[str_len] = '\0';
	
	vector<string*>* forms = Util::split(forms_line, '\t');
	vector<string*>* pos = Util::split(pos_line, '\t');
	vector<string*>* deprels = Util::split(deprel_line, '\t');
	vector<string*>* v = Util::split(heads_line, '\t');
	vector<int>* heads = Util::stringsToints(*v);
	vector<string*>::iterator iter;
	for(iter = v->begin(); iter != v->end(); iter++){
		pool->push_back(*iter);
	}
	delete(v);

	pool->push_back(forms_line);
	pool->push_back(pos_line);
	pool->push_back(deprel_line);
	pool->push_back(heads_line);

	vector<string*>* forms_new = new vector<string*>(forms->size() + 1);
	vector<string*>* pos_new = new vector<string*>(pos->size() + 1);
	vector<string*>* deprels_new = new vector<string*>(deprels->size() + 1);
	vector<int>* heads_new = new vector<int>(heads->size() + 1);

	tmp = string("<root>");
	(*forms_new)[0] = pool->get(tmp);
	tmp = string("<root-POS>");
	(*pos_new)[0] = pool->get(tmp);
	tmp = string("<no-type>");
	(*deprels_new)[0] = pool->get(tmp);
	(*heads_new)[0] = -1;

	int length = (int)(forms->size());
	for(int i = 0; i < length; ++i){
		(*forms_new)[i + 1] = normalize((*forms)[i]);
		pool->push_back((*forms)[i]);

		(*pos_new)[i + 1] = (*pos)[i];

		(*deprels_new)[i + 1] = labeled ? new string(*((*deprels)[i])) : new string("<no-type>");
		pool->push_back((*deprels)[i]);
		(*heads_new)[i + 1] = (*heads)[i];
	}

	delete(forms);
	delete(pos);
	delete(deprels);
	delete(heads);

	DependencyInstance* instance = new DependencyInstance(forms_new, pos_new, deprels_new, heads_new);
	
	vector<string*>* cpostags = new vector<string*>(pos_new->size());
	tmp = string("<root-CPOS>");
	(*cpostags)[0] = pool->get(tmp);

	length = (int)(pos_new->size());
	for(int i = 0; i < length; ++i){
		tmp = (*pos_new)[i]->substr(0, 1);
		(*cpostags)[i] = pool->get(tmp);
	}
	instance->cpostags = cpostags;

	vector<string*>* lemmas = new vector<string*>(forms_new->size());
	tmp = string("<root-LEMMA>");
	(*lemmas)[0] = pool->get(tmp);

	length = (int)(forms_new->size());
	for(int i = 1; i < length; ++i){
		int formLength = (int)((*forms_new)[i]->length());
		tmp = (*forms_new)[i]->substr(0, 5);
		(*lemmas)[i] = formLength > 5 ? pool->get(tmp) : pool->get(*((*forms_new)[i]));
	}

	instance->lemmas = lemmas;
	instance->feats = new vector<vector<string*>*>(0, new vector<string*>(0));
	return instance;
}

